<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"lanqilu.github.io","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":true},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#395ca3","save":"auto"},"fancybox":true,"mediumzoom":false,"lazyload":false,"pangu":true,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="Python面向对象编程参考Python-100-Days">
<meta property="og:type" content="article">
<meta property="og:title" content="面向对象编程">
<meta property="og:url" content="https://lanqilu.github.io/2019/06/30/Python/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B/index.html">
<meta property="og:site_name" content="Halo">
<meta property="og:description" content="Python面向对象编程参考Python-100-Days">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://pic.superbed.cn/item/5db304178b58bc7bf70c8b96.png">
<meta property="article:published_time" content="2019-06-30T13:34:50.000Z">
<meta property="article:modified_time" content="2020-07-06T07:16:49.459Z">
<meta property="article:author" content="Lanqilu">
<meta property="article:tag" content="Python">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://pic.superbed.cn/item/5db304178b58bc7bf70c8b96.png">

<link rel="canonical" href="https://lanqilu.github.io/2019/06/30/Python/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>面向对象编程 | Halo</title>
  
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-161500949-1"></script>
    <script data-pjax>
      if (CONFIG.hostname === location.hostname) {
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-161500949-1');
      }
    </script>


  <script data-pjax>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?256151d1651e9d73ec980b2fc69de8f6";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Halo</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签<span class="badge">39</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类<span class="badge">18</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档<span class="badge">85</span></a>

  </li>
        <li class="menu-item menu-item-python">

    <a href="/categories/Python/" rel="section"><i class="fa fa-fw fa-code"></i>Python</a>

  </li>
        <li class="menu-item menu-item-java">

    <a href="/categories/Java/" rel="section"><i class="fa fa-fw fa-code"></i>Java</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://lanqilu.github.io/2019/06/30/Python/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="http://img.whl123456.top/image/avatar.jpg">
      <meta itemprop="name" content="Lanqilu">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Halo">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          面向对象编程
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-06-30 21:34:50" itemprop="dateCreated datePublished" datetime="2019-06-30T21:34:50+08:00">2019-06-30</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-07-06 15:16:49" itemprop="dateModified" datetime="2020-07-06T15:16:49+08:00">2020-07-06</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Python/" itemprop="url" rel="index"><span itemprop="name">Python</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <div class="note info no-icon">
            <p>Python面向对象编程参考<a href="https://github.com/jackfrued/Python-100-Days" target="_blank" rel="noopener">Python-100-Days</a></p>
          </div>

<a id="more"></a>

<p><img src="https://pic.superbed.cn/item/5db304178b58bc7bf70c8b96.png" alt=""></p>
<hr>
<h3 id="property装饰器"><a href="#property装饰器" class="headerlink" title="@property装饰器"></a>@property装饰器</h3><p>之前我们讨论过Python中属性和方法访问权限的问题，虽然我们不建议将属性设置为私有的，但是如果直接将属性暴露给外界也是有问题的，比如我们没有办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头，通过这种方式来暗示属性是受保护的，不建议外界直接访问，那么如果想访问属性可以通过属性的getter（访问器）和setter（修改器）方法进行对应的操作。如果要做到这点，就可以考虑使用@property包装器来包装getter和setter方法，使得对属性的访问既安全又方便，代码如下所示。</p>
<!--more-->
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age)</span>:</span></span><br><span class="line">        self._name = name</span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 访问器 - getter方法</span></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 访问器 - getter方法</span></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._age</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 修改器 - setter方法</span></span><br><span class="line"><span class="meta">    @age.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self, age)</span>:</span></span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">play</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self._age &lt;= <span class="number">16</span>:</span><br><span class="line">            print(<span class="string">'%s正在玩飞行棋.'</span> % self._name)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">'%s正在玩斗地主.'</span> % self._name)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    person = Person(<span class="string">'王大锤'</span>, <span class="number">12</span>)</span><br><span class="line">    person.play()</span><br><span class="line">    person.age = <span class="number">22</span></span><br><span class="line">    person.play()</span><br><span class="line">    <span class="comment"># person.name = '白元芳'  # AttributeError: can't set attribute</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h3 id="slots-魔法"><a href="#slots-魔法" class="headerlink" title="__slots__魔法"></a>__slots__魔法</h3><p>我们讲到这里，不知道大家是否已经意识到，Python是一门<a href="https://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%AF%AD%E8%A8%80" target="_blank" rel="noopener">动态语言</a>。通常，动态语言允许我们在程序运行时给对象绑定新的属性或方法，当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性，可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效，对子类并不起任何作用。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 限定Person对象只能绑定_name, _age和_gender属性</span></span><br><span class="line">    __slots__ = (<span class="string">'_name'</span>, <span class="string">'_age'</span>, <span class="string">'_gender'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age)</span>:</span></span><br><span class="line">        self._name = name</span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._age</span><br><span class="line"></span><br><span class="line"><span class="meta">    @age.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self, age)</span>:</span></span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">play</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self._age &lt;= <span class="number">16</span>:</span><br><span class="line">            print(<span class="string">'%s正在玩飞行棋.'</span> % self._name)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">'%s正在玩斗地主.'</span> % self._name)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    person = Person(<span class="string">'王大锤'</span>, <span class="number">22</span>)</span><br><span class="line">    person.play()</span><br><span class="line">    person._gender = <span class="string">'男'</span></span><br><span class="line">    <span class="comment"># AttributeError: 'Person' object has no attribute '_is_gay'</span></span><br><span class="line">    <span class="comment"># person._is_gay = True</span></span><br></pre></td></tr></table></figure>

<h3 id="静态方法和类方法"><a href="#静态方法和类方法" class="headerlink" title="静态方法和类方法"></a>静态方法和类方法</h3><p>之前，我们在类中定义的方法都是对象方法，也就是说这些方法都是发送给对象的消息。实际上，我们写在类中的方法并不需要都是对象方法，例如我们定义一个“三角形”类，通过传入三条边长来构造三角形，并提供计算周长和面积的方法，但是传入的三条边长未必能构造出三角形对象，因此我们可以先写一个方法来验证三条边长是否可以构成三角形，这个方法很显然就不是对象方法，因为在调用这个方法时三角形对象尚未创建出来（因为都不知道三条边能不能构成三角形），所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题，代码如下所示。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> math <span class="keyword">import</span> sqrt</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Triangle</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, a, b, c)</span>:</span></span><br><span class="line">        self._a = a</span><br><span class="line">        self._b = b</span><br><span class="line">        self._c = c</span><br><span class="line"></span><br><span class="line"><span class="meta">    @staticmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">is_valid</span><span class="params">(a, b, c)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> a + b &gt; c <span class="keyword">and</span> b + c &gt; a <span class="keyword">and</span> a + c &gt; b</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">perimeter</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._a + self._b + self._c</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">area</span><span class="params">(self)</span>:</span></span><br><span class="line">        half = self.perimeter() / <span class="number">2</span></span><br><span class="line">        <span class="keyword">return</span> sqrt(half * (half - self._a) *</span><br><span class="line">                    (half - self._b) * (half - self._c))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    a, b, c = <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span></span><br><span class="line">    <span class="comment"># 静态方法和类方法都是通过给类发消息来调用的</span></span><br><span class="line">    <span class="keyword">if</span> Triangle.is_valid(a, b, c):</span><br><span class="line">        t = Triangle(a, b, c)</span><br><span class="line">        print(t.perimeter())</span><br><span class="line">        <span class="comment"># 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数</span></span><br><span class="line">        <span class="comment"># print(Triangle.perimeter(t))</span></span><br><span class="line">        print(t.area())</span><br><span class="line">        <span class="comment"># print(Triangle.area(t))</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        print(<span class="string">'无法构成三角形.'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<p>和静态方法比较类似，Python还可以在类中定义类方法，类方法的第一个参数约定名为cls，它代表的是当前类相关的信息的对象（类本身也是一个对象，有的地方也称之为类的元数据对象），通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象，代码如下所示。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> time, localtime, sleep</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Clock</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">"""数字时钟"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, hour=<span class="number">0</span>, minute=<span class="number">0</span>, second=<span class="number">0</span>)</span>:</span></span><br><span class="line">        self._hour = hour</span><br><span class="line">        self._minute = minute</span><br><span class="line">        self._second = second</span><br><span class="line"></span><br><span class="line"><span class="meta">    @classmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">now</span><span class="params">(cls)</span>:</span></span><br><span class="line">        ctime = localtime(time())</span><br><span class="line">        <span class="keyword">return</span> cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""走字"""</span></span><br><span class="line">        self._second += <span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> self._second == <span class="number">60</span>:</span><br><span class="line">            self._second = <span class="number">0</span></span><br><span class="line">            self._minute += <span class="number">1</span></span><br><span class="line">            <span class="keyword">if</span> self._minute == <span class="number">60</span>:</span><br><span class="line">                self._minute = <span class="number">0</span></span><br><span class="line">                self._hour += <span class="number">1</span></span><br><span class="line">                <span class="keyword">if</span> self._hour == <span class="number">24</span>:</span><br><span class="line">                    self._hour = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">show</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""显示时间"""</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'%02d:%02d:%02d'</span> % \</span><br><span class="line">               (self._hour, self._minute, self._second)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    <span class="comment"># 通过类方法创建对象并获取系统时间</span></span><br><span class="line">    clock = Clock.now()</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        print(clock.show())</span><br><span class="line">        sleep(<span class="number">1</span>)</span><br><span class="line">        clock.run()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h3 id="类之间的关系"><a href="#类之间的关系" class="headerlink" title="类之间的关系"></a>类之间的关系</h3><p>简单的说，类和类之间的关系有三种：is-a、has-a和use-a关系。</p>
<ul>
<li>is-a关系也叫继承或泛化，比如学生和人的关系、手机和电子产品的关系都属于继承关系。</li>
<li>has-a关系通常称之为关联，比如部门和员工的关系，汽车和引擎的关系都属于关联关系；关联关系如果是整体和部分的关联，那么我们称之为聚合关系；如果整体进一步负责了部分的生命周期（整体和部分是不可分割的，同时同在也同时消亡），那么这种就是最强的关联关系，我们称之为合成关系。</li>
<li>use-a关系通常称之为依赖，比如司机有一个驾驶的行为（方法），其中（的参数）使用到了汽车，那么司机和汽车的关系就是依赖关系。</li>
</ul>
<p>利用类之间的这些关系，我们可以在已有类的基础上来完成某些操作，也可以在已有类的基础上创建新的类，这些都是实现代码复用的重要手段。复用现有的代码不仅可以减少开发的工作量，也有利于代码的管理和维护，这是我们在日常工作中都会使用到的技术手段。</p>
<h3 id="继承和多态"><a href="#继承和多态" class="headerlink" title="继承和多态"></a>继承和多态</h3><p>刚才我们提到了，可以在已有类的基础上创建新类，这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来，从而减少重复代码的编写。提供继承信息的我们称之为父类，也叫超类或基类；得到继承信息的我们称之为子类，也叫派生类或衍生类。子类除了继承父类提供的属性和方法，还可以定义自己特有的属性和方法，所以子类比父类拥有的更多的能力，在实际开发中，我们经常会用子类对象去替换掉一个父类对象，这是面向对象编程中一个常见的行为，对应的原则称之为<a href="https://zh.wikipedia.org/wiki/%E9%87%8C%E6%B0%8F%E6%9B%BF%E6%8D%A2%E5%8E%9F%E5%88%99" target="_blank" rel="noopener">里氏替换原则</a>。下面我们先看一个继承的例子。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">"""人"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age)</span>:</span></span><br><span class="line">        self._name = name</span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._age</span><br><span class="line"></span><br><span class="line"><span class="meta">    @age.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self, age)</span>:</span></span><br><span class="line">        self._age = age</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">play</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'%s正在愉快的玩耍.'</span> % self._name)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">watch_av</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self._age &gt;= <span class="number">18</span>:</span><br><span class="line">            print(<span class="string">'%s正在观看爱情动作片.'</span> % self._name)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            print(<span class="string">'%s只能观看《熊出没》.'</span> % self._name)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(Person)</span>:</span></span><br><span class="line">    <span class="string">"""学生"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age, grade)</span>:</span></span><br><span class="line">        super().__init__(name, age)</span><br><span class="line">        self._grade = grade</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">grade</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._grade</span><br><span class="line"></span><br><span class="line"><span class="meta">    @grade.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">grade</span><span class="params">(self, grade)</span>:</span></span><br><span class="line">        self._grade = grade</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">study</span><span class="params">(self, course)</span>:</span></span><br><span class="line">        print(<span class="string">'%s的%s正在学习%s.'</span> % (self._grade, self._name, course))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Teacher</span><span class="params">(Person)</span>:</span></span><br><span class="line">    <span class="string">"""老师"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age, title)</span>:</span></span><br><span class="line">        super().__init__(name, age)</span><br><span class="line">        self._title = title</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">title</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._title</span><br><span class="line"></span><br><span class="line"><span class="meta">    @title.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">title</span><span class="params">(self, title)</span>:</span></span><br><span class="line">        self._title = title</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">teach</span><span class="params">(self, course)</span>:</span></span><br><span class="line">        print(<span class="string">'%s%s正在讲%s.'</span> % (self._name, self._title, course))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    stu = Student(<span class="string">'王大锤'</span>, <span class="number">15</span>, <span class="string">'初三'</span>)</span><br><span class="line">    stu.study(<span class="string">'数学'</span>)</span><br><span class="line">    stu.watch_av()</span><br><span class="line">    t = Teacher(<span class="string">'骆昊'</span>, <span class="number">38</span>, <span class="string">'砖家'</span>)</span><br><span class="line">    t.teach(<span class="string">'Python程序设计'</span>)</span><br><span class="line">    t.watch_av()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<p>子类在继承了父类的方法后，可以对父类已有的方法给出新的实现版本，这个动作称之为方法重写（override）。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本，当我们调用这个经过子类重写的方法时，不同的子类对象会表现出不同的行为，这个就是多态（poly-morphism）。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> abc <span class="keyword">import</span> ABCMeta, abstractmethod</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Pet</span><span class="params">(object, metaclass=ABCMeta)</span>:</span></span><br><span class="line">    <span class="string">"""宠物"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, nickname)</span>:</span></span><br><span class="line">        self._nickname = nickname</span><br><span class="line"></span><br><span class="line"><span class="meta">    @abstractmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">make_voice</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""发出声音"""</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span><span class="params">(Pet)</span>:</span></span><br><span class="line">    <span class="string">"""狗"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">make_voice</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'%s: 汪汪汪...'</span> % self._nickname)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span><span class="params">(Pet)</span>:</span></span><br><span class="line">    <span class="string">"""猫"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">make_voice</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'%s: 喵...喵...'</span> % self._nickname)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    pets = [Dog(<span class="string">'旺财'</span>), Cat(<span class="string">'凯蒂'</span>), Dog(<span class="string">'大黄'</span>)]</span><br><span class="line">    <span class="keyword">for</span> pet <span class="keyword">in</span> pets:</span><br><span class="line">        pet.make_voice()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们将<code>Pet</code>类处理成了一个抽象类，所谓抽象类就是不能够创建对象的类，这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持，但是我们可以通过<code>abc</code>模块的<code>ABCMeta</code>元类和<code>abstractmethod</code>包装器来达到抽象类的效果，如果一个类中存在抽象方法那么这个类就不能够实例化（创建对象）。上面的代码中，<code>Dog</code>和<code>Cat</code>两个子类分别对<code>Pet</code>类中的<code>make_voice</code>抽象方法进行了重写并给出了不同的实现版本，当我们在<code>main</code>函数中调用该方法时，这个方法就表现出了多态行为（同样的方法做了不同的事情）。</p>
<h3 id="综合案例"><a href="#综合案例" class="headerlink" title="综合案例"></a>综合案例</h3><h4 id="案例1：奥特曼打小怪兽"><a href="#案例1：奥特曼打小怪兽" class="headerlink" title="案例1：奥特曼打小怪兽"></a>案例1：奥特曼打小怪兽</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> abc <span class="keyword">import</span> ABCMeta, abstractmethod</span><br><span class="line"><span class="keyword">from</span> random <span class="keyword">import</span> randint, randrange</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Fighter</span><span class="params">(object, metaclass=ABCMeta)</span>:</span></span><br><span class="line">    <span class="string">"""战斗者"""</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 通过__slots__魔法限定对象可以绑定的成员变量</span></span><br><span class="line">    __slots__ = (<span class="string">'_name'</span>, <span class="string">'_hp'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, hp)</span>:</span></span><br><span class="line">        <span class="string">"""初始化方法</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param name: 名字</span></span><br><span class="line"><span class="string">        :param hp: 生命值</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        self._name = name</span><br><span class="line">        self._hp = hp</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hp</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._hp</span><br><span class="line"></span><br><span class="line"><span class="meta">    @hp.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hp</span><span class="params">(self, hp)</span>:</span></span><br><span class="line">        self._hp = hp <span class="keyword">if</span> hp &gt;= <span class="number">0</span> <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">alive</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._hp &gt; <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @abstractmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">attack</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="string">"""攻击</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param other: 被攻击的对象</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ultraman</span><span class="params">(Fighter)</span>:</span></span><br><span class="line">    <span class="string">"""奥特曼"""</span></span><br><span class="line"></span><br><span class="line">    __slots__ = (<span class="string">'_name'</span>, <span class="string">'_hp'</span>, <span class="string">'_mp'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, hp, mp)</span>:</span></span><br><span class="line">        <span class="string">"""初始化方法</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param name: 名字</span></span><br><span class="line"><span class="string">        :param hp: 生命值</span></span><br><span class="line"><span class="string">        :param mp: 魔法值</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        super().__init__(name, hp)</span><br><span class="line">        self._mp = mp</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">attack</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        other.hp -= randint(<span class="number">15</span>, <span class="number">25</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">huge_attack</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="string">"""究极必杀技(打掉对方至少50点或四分之三的血)</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param other: 被攻击的对象</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return: 使用成功返回True否则返回False</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">if</span> self._mp &gt;= <span class="number">50</span>:</span><br><span class="line">            self._mp -= <span class="number">50</span></span><br><span class="line">            injury = other.hp * <span class="number">3</span> // <span class="number">4</span></span><br><span class="line">            injury = injury <span class="keyword">if</span> injury &gt;= <span class="number">50</span> <span class="keyword">else</span> <span class="number">50</span></span><br><span class="line">            other.hp -= injury</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.attack(other)</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">magic_attack</span><span class="params">(self, others)</span>:</span></span><br><span class="line">        <span class="string">"""魔法攻击</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param others: 被攻击的群体</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return: 使用魔法成功返回True否则返回False</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">if</span> self._mp &gt;= <span class="number">20</span>:</span><br><span class="line">            self._mp -= <span class="number">20</span></span><br><span class="line">            <span class="keyword">for</span> temp <span class="keyword">in</span> others:</span><br><span class="line">                <span class="keyword">if</span> temp.alive:</span><br><span class="line">                    temp.hp -= randint(<span class="number">10</span>, <span class="number">15</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">resume</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""恢复魔法值"""</span></span><br><span class="line">        incr_point = randint(<span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line">        self._mp += incr_point</span><br><span class="line">        <span class="keyword">return</span> incr_point</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'~~~%s奥特曼~~~\n'</span> % self._name + \</span><br><span class="line">            <span class="string">'生命值: %d\n'</span> % self._hp + \</span><br><span class="line">            <span class="string">'魔法值: %d\n'</span> % self._mp</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Monster</span><span class="params">(Fighter)</span>:</span></span><br><span class="line">    <span class="string">"""小怪兽"""</span></span><br><span class="line"></span><br><span class="line">    __slots__ = (<span class="string">'_name'</span>, <span class="string">'_hp'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">attack</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        other.hp -= randint(<span class="number">10</span>, <span class="number">20</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">'~~~%s小怪兽~~~\n'</span> % self._name + \</span><br><span class="line">            <span class="string">'生命值: %d\n'</span> % self._hp</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">is_any_alive</span><span class="params">(monsters)</span>:</span></span><br><span class="line">    <span class="string">"""判断有没有小怪兽是活着的"""</span></span><br><span class="line">    <span class="keyword">for</span> monster <span class="keyword">in</span> monsters:</span><br><span class="line">        <span class="keyword">if</span> monster.alive &gt; <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">select_alive_one</span><span class="params">(monsters)</span>:</span></span><br><span class="line">    <span class="string">"""选中一只活着的小怪兽"""</span></span><br><span class="line">    monsters_len = len(monsters)</span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        index = randrange(monsters_len)</span><br><span class="line">        monster = monsters[index]</span><br><span class="line">        <span class="keyword">if</span> monster.alive &gt; <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">return</span> monster</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">display_info</span><span class="params">(ultraman, monsters)</span>:</span></span><br><span class="line">    <span class="string">"""显示奥特曼和小怪兽的信息"""</span></span><br><span class="line">    print(ultraman)</span><br><span class="line">    <span class="keyword">for</span> monster <span class="keyword">in</span> monsters:</span><br><span class="line">        print(monster, end=<span class="string">''</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    u = Ultraman(<span class="string">'骆昊'</span>, <span class="number">1000</span>, <span class="number">120</span>)</span><br><span class="line">    m1 = Monster(<span class="string">'狄仁杰'</span>, <span class="number">250</span>)</span><br><span class="line">    m2 = Monster(<span class="string">'白元芳'</span>, <span class="number">500</span>)</span><br><span class="line">    m3 = Monster(<span class="string">'王大锤'</span>, <span class="number">750</span>)</span><br><span class="line">    ms = [m1, m2, m3]</span><br><span class="line">    fight_round = <span class="number">1</span></span><br><span class="line">    <span class="keyword">while</span> u.alive <span class="keyword">and</span> is_any_alive(ms):</span><br><span class="line">        print(<span class="string">'========第%02d回合========'</span> % fight_round)</span><br><span class="line">        m = select_alive_one(ms)  <span class="comment"># 选中一只小怪兽</span></span><br><span class="line">        skill = randint(<span class="number">1</span>, <span class="number">10</span>)   <span class="comment"># 通过随机数选择使用哪种技能</span></span><br><span class="line">        <span class="keyword">if</span> skill &lt;= <span class="number">6</span>:  <span class="comment"># 60%的概率使用普通攻击</span></span><br><span class="line">            print(<span class="string">'%s使用普通攻击打了%s.'</span> % (u.name, m.name))</span><br><span class="line">            u.attack(m)</span><br><span class="line">            print(<span class="string">'%s的魔法值恢复了%d点.'</span> % (u.name, u.resume()))</span><br><span class="line">        <span class="keyword">elif</span> skill &lt;= <span class="number">9</span>:  <span class="comment"># 30%的概率使用魔法攻击(可能因魔法值不足而失败)</span></span><br><span class="line">            <span class="keyword">if</span> u.magic_attack(ms):</span><br><span class="line">                print(<span class="string">'%s使用了魔法攻击.'</span> % u.name)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                print(<span class="string">'%s使用魔法失败.'</span> % u.name)</span><br><span class="line">        <span class="keyword">else</span>:  <span class="comment"># 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)</span></span><br><span class="line">            <span class="keyword">if</span> u.huge_attack(m):</span><br><span class="line">                print(<span class="string">'%s使用究极必杀技虐了%s.'</span> % (u.name, m.name))</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                print(<span class="string">'%s使用普通攻击打了%s.'</span> % (u.name, m.name))</span><br><span class="line">                print(<span class="string">'%s的魔法值恢复了%d点.'</span> % (u.name, u.resume()))</span><br><span class="line">        <span class="keyword">if</span> m.alive &gt; <span class="number">0</span>:  <span class="comment"># 如果选中的小怪兽没有死就回击奥特曼</span></span><br><span class="line">            print(<span class="string">'%s回击了%s.'</span> % (m.name, u.name))</span><br><span class="line">            m.attack(u)</span><br><span class="line">        display_info(u, ms)  <span class="comment"># 每个回合结束后显示奥特曼和小怪兽的信息</span></span><br><span class="line">        fight_round += <span class="number">1</span></span><br><span class="line">    print(<span class="string">'\n========战斗结束!========\n'</span>)</span><br><span class="line">    <span class="keyword">if</span> u.alive &gt; <span class="number">0</span>:</span><br><span class="line">        print(<span class="string">'%s奥特曼胜利!'</span> % u.name)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        print(<span class="string">'小怪兽胜利!'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="案例2：扑克游戏"><a href="#案例2：扑克游戏" class="headerlink" title="案例2：扑克游戏"></a>案例2：扑克游戏</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Card</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">"""一张牌"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, suite, face)</span>:</span></span><br><span class="line">        self._suite = suite</span><br><span class="line">        self._face = face</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">face</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._face</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">suite</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._suite</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self._face == <span class="number">1</span>:</span><br><span class="line">            face_str = <span class="string">'A'</span></span><br><span class="line">        <span class="keyword">elif</span> self._face == <span class="number">11</span>:</span><br><span class="line">            face_str = <span class="string">'J'</span></span><br><span class="line">        <span class="keyword">elif</span> self._face == <span class="number">12</span>:</span><br><span class="line">            face_str = <span class="string">'Q'</span></span><br><span class="line">        <span class="keyword">elif</span> self._face == <span class="number">13</span>:</span><br><span class="line">            face_str = <span class="string">'K'</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            face_str = str(self._face)</span><br><span class="line">        <span class="keyword">return</span> <span class="string">'%s%s'</span> % (self._suite, face_str)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__repr__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.__str__()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Poker</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">"""一副牌"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        self._cards = [Card(suite, face)</span><br><span class="line">                       <span class="keyword">for</span> suite <span class="keyword">in</span> <span class="string">'♠♥♣♦'</span></span><br><span class="line">                       <span class="keyword">for</span> face <span class="keyword">in</span> range(<span class="number">1</span>, <span class="number">14</span>)]</span><br><span class="line">        self._current = <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cards</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._cards</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">shuffle</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""洗牌(随机乱序)"""</span></span><br><span class="line">        self._current = <span class="number">0</span></span><br><span class="line">        random.shuffle(self._cards)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">next</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""发牌"""</span></span><br><span class="line">        card = self._cards[self._current]</span><br><span class="line">        self._current += <span class="number">1</span></span><br><span class="line">        <span class="keyword">return</span> card</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">has_next</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""还有没有牌"""</span></span><br><span class="line">        <span class="keyword">return</span> self._current &lt; len(self._cards)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Player</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">"""玩家"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name)</span>:</span></span><br><span class="line">        self._name = name</span><br><span class="line">        self._cards_on_hand = []</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cards_on_hand</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._cards_on_hand</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get</span><span class="params">(self, card)</span>:</span></span><br><span class="line">        <span class="string">"""摸牌"""</span></span><br><span class="line">        self._cards_on_hand.append(card)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">arrange</span><span class="params">(self, card_key)</span>:</span></span><br><span class="line">        <span class="string">"""玩家整理手上的牌"""</span></span><br><span class="line">        self._cards_on_hand.sort(key=card_key)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 排序规则-先根据花色再根据点数排序</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_key</span><span class="params">(card)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> (card.suite, card.face)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    p = Poker()</span><br><span class="line">    p.shuffle()</span><br><span class="line">    players = [Player(<span class="string">'东邪'</span>), Player(<span class="string">'西毒'</span>), Player(<span class="string">'南帝'</span>), Player(<span class="string">'北丐'</span>)]</span><br><span class="line">    <span class="keyword">for</span> _ <span class="keyword">in</span> range(<span class="number">13</span>):</span><br><span class="line">        <span class="keyword">for</span> player <span class="keyword">in</span> players:</span><br><span class="line">            player.get(p.next)</span><br><span class="line">    <span class="keyword">for</span> player <span class="keyword">in</span> players:</span><br><span class="line">        print(player.name + <span class="string">':'</span>, end=<span class="string">' '</span>)</span><br><span class="line">        player.arrange(get_key)</span><br><span class="line">        print(player.cards_on_hand)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>说明：</strong> 大家可以自己尝试在上面代码的基础上写一个简单的扑克游戏，例如21点(Black Jack)，游戏的规则可以自己在网上找一找。</p>
</blockquote>
<h4 id="案例3：工资结算系统"><a href="#案例3：工资结算系统" class="headerlink" title="案例3：工资结算系统"></a>案例3：工资结算系统</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">某公司有三种类型的员工 分别是部门经理、程序员和销售员</span></span><br><span class="line"><span class="string">需要设计一个工资结算系统 根据提供的员工信息来计算月薪</span></span><br><span class="line"><span class="string">部门经理的月薪是每月固定15000元</span></span><br><span class="line"><span class="string">程序员的月薪按本月工作时间计算 每小时150元</span></span><br><span class="line"><span class="string">销售员的月薪是1200元的底薪加上销售额5%的提成</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="keyword">from</span> abc <span class="keyword">import</span> ABCMeta, abstractmethod</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Employee</span><span class="params">(object, metaclass=ABCMeta)</span>:</span></span><br><span class="line">    <span class="string">"""员工"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        初始化方法</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :param name: 姓名</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        self._name = name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">name</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._name</span><br><span class="line"></span><br><span class="line"><span class="meta">    @abstractmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_salary</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        获得月薪</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        :return: 月薪</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Manager</span><span class="params">(Employee)</span>:</span></span><br><span class="line">    <span class="string">"""部门经理"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_salary</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">15000.0</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Programmer</span><span class="params">(Employee)</span>:</span></span><br><span class="line">    <span class="string">"""程序员"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, working_hour=<span class="number">0</span>)</span>:</span></span><br><span class="line">        super().__init__(name)</span><br><span class="line">        self._working_hour = working_hour</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">working_hour</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._working_hour</span><br><span class="line"></span><br><span class="line"><span class="meta">    @working_hour.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">working_hour</span><span class="params">(self, working_hour)</span>:</span></span><br><span class="line">        self._working_hour = working_hour <span class="keyword">if</span> working_hour &gt; <span class="number">0</span> <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_salary</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">150.0</span> * self._working_hour</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Salesman</span><span class="params">(Employee)</span>:</span></span><br><span class="line">    <span class="string">"""销售员"""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, sales=<span class="number">0</span>)</span>:</span></span><br><span class="line">        super().__init__(name)</span><br><span class="line">        self._sales = sales</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">sales</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._sales</span><br><span class="line"></span><br><span class="line"><span class="meta">    @sales.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">sales</span><span class="params">(self, sales)</span>:</span></span><br><span class="line">        self._sales = sales <span class="keyword">if</span> sales &gt; <span class="number">0</span> <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_salary</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">1200.0</span> + self._sales * <span class="number">0.05</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line">    emps = [</span><br><span class="line">        Manager(<span class="string">'刘备'</span>), Programmer(<span class="string">'诸葛亮'</span>),</span><br><span class="line">        Manager(<span class="string">'曹操'</span>), Salesman(<span class="string">'荀彧'</span>),</span><br><span class="line">        Salesman(<span class="string">'吕布'</span>), Programmer(<span class="string">'张辽'</span>),</span><br><span class="line">        Programmer(<span class="string">'赵云'</span>)</span><br><span class="line">    ]</span><br><span class="line">    <span class="keyword">for</span> emp <span class="keyword">in</span> emps:</span><br><span class="line">        <span class="keyword">if</span> isinstance(emp, Programmer):</span><br><span class="line">            emp.working_hour = int(input(<span class="string">'请输入%s本月工作时间: '</span> % emp.name))</span><br><span class="line">        <span class="keyword">elif</span> isinstance(emp, Salesman):</span><br><span class="line">            emp.sales = float(input(<span class="string">'请输入%s本月销售额: '</span> % emp.name))</span><br><span class="line">        <span class="comment"># 同样是接收get_salary这个消息但是不同的员工表现出了不同的行为(多态)</span></span><br><span class="line">        print(<span class="string">'%s本月工资为: ￥%s元'</span> %</span><br><span class="line">              (emp.name, emp.get_salary()))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

    </div>

    
    
    
      
  <div class="popular-posts-header">相关文章</div>
  <ul class="popular-posts">
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\03\23\Java\Java书单\" rel="bookmark">计算机书单</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\03\24\Python\Python网络数据采集\" rel="bookmark">Python网络数据采集</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\04\06\Python\Django\" rel="bookmark">Django</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2020\03\27\Python\正则表达式\" rel="bookmark">正则表达式</a></div>
    </li>
    <li class="popular-posts-item">
      <div class="popular-posts-title"><a href="\2019\10\01\Python\函数式编程\" rel="bookmark">函数式编程</a></div>
    </li>
  </ul>


      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/Python/" rel="tag"><i class="fa fa-tag"></i> Python</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/06/27/DevelopTools/Vim%E5%9F%BA%E7%A1%80/" rel="prev" title="Vim简单使用">
      <i class="fa fa-chevron-left"></i> Vim简单使用
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/07/22/Python/%E7%A7%91%E5%AD%A6%E8%AE%A1%E7%AE%97%E4%B9%8BNumPy/" rel="next" title="科学计算之NumPy">
      科学计算之NumPy <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#property装饰器"><span class="nav-number">1.</span> <span class="nav-text">@property装饰器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#slots-魔法"><span class="nav-number">2.</span> <span class="nav-text">__slots__魔法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#静态方法和类方法"><span class="nav-number">3.</span> <span class="nav-text">静态方法和类方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#类之间的关系"><span class="nav-number">4.</span> <span class="nav-text">类之间的关系</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#继承和多态"><span class="nav-number">5.</span> <span class="nav-text">继承和多态</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#综合案例"><span class="nav-number">6.</span> <span class="nav-text">综合案例</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#案例1：奥特曼打小怪兽"><span class="nav-number">6.1.</span> <span class="nav-text">案例1：奥特曼打小怪兽</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#案例2：扑克游戏"><span class="nav-number">6.2.</span> <span class="nav-text">案例2：扑克游戏</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#案例3：工资结算系统"><span class="nav-number">6.3.</span> <span class="nav-text">案例3：工资结算系统</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Lanqilu"
      src="http://img.whl123456.top/image/avatar.jpg">
  <p class="site-author-name" itemprop="name">Lanqilu</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">85</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">39</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/lanqilu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;lanqilu" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i></a>
      </span>
      <span class="links-of-author-item">
        <a href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=zqKvoL_noruOqKG2o6_nouCtoaM" title="E-Mail → http:&#x2F;&#x2F;mail.qq.com&#x2F;cgi-bin&#x2F;qm_share?t&#x3D;qm_mailme&amp;email&#x3D;zqKvoL_noruOqKG2o6_nouCtoaM" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i></a>
      </span>
  </div>



      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2019 – 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Lanqilu</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/pjax/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '.languages',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[data-pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.dataset.pjax !== undefined) {
      script.dataset.pjax = '';
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="/js/local-search.js"></script>













    <div id="pjax">
  

  

  

    </div>
</body>
</html>
